package com.xyazm.order.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyazm.common.enums.AfterSaleApplySourceEnum;
import com.xyazm.common.enums.AfterSaleTypeDetailEnum;
import com.xyazm.common.exception.BaseBusinessErrorCodeEnum;
import com.xyazm.common.page.PagingInfo;
import com.xyazm.common.utils.ParamCheckUtil;
import com.xyazm.order.dao.AfterSaleInfoDAO;
import com.xyazm.order.dao.AfterSaleItemDAO;
import com.xyazm.order.dao.AfterSaleLogDAO;
import com.xyazm.order.dao.AfterSaleRefundDAO;
import com.xyazm.order.domain.builder.AfterSaleOrderDetailBuilder;
import com.xyazm.order.domain.dto.AfterSaleOrderDetailDTO;
import com.xyazm.order.domain.dto.AfterSaleOrderListDTO;
import com.xyazm.order.domain.dto.OrderLackItemDTO;
import com.xyazm.order.domain.dto.QueryAfterSaleListDTO;
import com.xyazm.order.domain.entity.AfterSaleInfoDO;
import com.xyazm.order.domain.entity.AfterSaleItemDO;
import com.xyazm.order.domain.entity.AfterSaleLogDO;
import com.xyazm.order.domain.entity.AfterSaleRefundDO;
import com.xyazm.order.domain.param.QueryAfterSaleParam;
import com.xyazm.order.enums.AfterSaleStatusEnum;
import com.xyazm.order.enums.BusinessIdentifierEnum;
import com.xyazm.common.enums.OrderTypeEnum;
import com.xyazm.order.exception.OrderErrorCodeEnum;
import com.xyazm.order.service.IAfterSaleQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
@Service
public class AfterSaleQueryServiceImpl implements IAfterSaleQueryService {

    @Autowired
    private AfterSaleInfoDAO afterSaleInfoDAO;
    @Autowired
    private AfterSaleItemDAO afterSaleItemDAO;
    @Autowired
    private AfterSaleLogDAO afterSaleLogDAO;
    @Autowired
    private AfterSaleRefundDAO afterSaleRefundDAO;

    @Override
    public PagingInfo<AfterSaleOrderListDTO> listAfterSales(QueryAfterSaleParam param) {
        // 校验查询列表入参
        checkQueryAfterSaleParam(param);
        // 第一阶段采用连表查询,第二阶段会接入es
        // 1.组装业务查询规则
        QueryAfterSaleListDTO queryDTO = QueryAfterSaleListDTO.Builder.builder()
                .copy(param)
                //默认只展示用户主动发起的售后单
                .userApplySource()
                .setPage(param)
                .build();
        // 2.查询DB
        Page<AfterSaleOrderListDTO> page = afterSaleInfoDAO.listByPage(queryDTO);
        // 3.转化
        return PagingInfo.toResponse(page.getRecords(),
                page.getTotal(), (int)page.getCurrent(), (int) page.getSize());
    }

    @Override
    public AfterSaleOrderDetailDTO afterSaleDetail(String afterSaleId) {
        //1、查询售后单
        AfterSaleInfoDO afterSaleInfoDO = afterSaleInfoDAO.getOneByAfterSaleId(afterSaleId);
        if(afterSaleInfoDO == null) {
            return null;
        }
        //2、查询售后单条目
        List<AfterSaleItemDO> afterSaleItems = afterSaleItemDAO.listByAfterSaleId(afterSaleId);
        //3、查询售后信息
        List<AfterSaleRefundDO> afterSaleRefunds = afterSaleRefundDAO.listByAfterSaleId(afterSaleId);
        //4、查询售后日志
        List<AfterSaleLogDO> afterSaleLogs = afterSaleLogDAO.listByAfterSaleId(afterSaleId);
        //5、构造返参
        return new AfterSaleOrderDetailBuilder()
                .afterSaleInfo(afterSaleInfoDO)
                .afterSaleItems(afterSaleItems)
                .afterSaleRefunds(afterSaleRefunds)
                .afterSaleLogs(afterSaleLogs)
                .build();
    }

    @Override
    public List<OrderLackItemDTO> getOrderLackItemInfo(String orderId) {
        // 根据订单号查询售后类型为缺品的售后单
        List<AfterSaleInfoDO> lackItemDO = afterSaleInfoDAO.listByOrderIdAndAfterSaleType(orderId
                , AfterSaleTypeDetailEnum.LACK_REFUND.getCode());
        if(CollectionUtils.isEmpty(lackItemDO)) {
            return null;
        }
        List<OrderLackItemDTO> lackItems = new ArrayList<>();
        lackItemDO.forEach(lackItem -> {
            AfterSaleOrderDetailDTO detailDTO = afterSaleDetail(lackItem.getAfterSaleId());
            OrderLackItemDTO itemDTO = new OrderLackItemDTO();
            BeanUtils.copyProperties(detailDTO,itemDTO);
            lackItems.add(itemDTO);
        });
        return lackItems;
    }

    /**
     * 校验查询列表入参
     * @author xuyou
     * @date: 2022/7/21 16:28
     */
    private void checkQueryAfterSaleParam(QueryAfterSaleParam param) {
        // 校验 业务线 传值是否正确
        ParamCheckUtil.checkObjectNonNull(param.getBusinessIdentifier(), OrderErrorCodeEnum.BUSINESS_IDENTIFIER_IS_NULL);
        ParamCheckUtil.checkIntAllowableValues(
                param.getBusinessIdentifier(),
                BusinessIdentifierEnum.allowableValues(),
                BaseBusinessErrorCodeEnum.ENUM_PARAM_MUST_BE_IN_ALLOWABLE_VALUE,
                "businessIdentifier",
                BusinessIdentifierEnum.allowableValues());

        // 校验 订单类型 传值是否正确
        ParamCheckUtil.checkIntSetAllowableValues(
                param.getOrderTypes(),
                OrderTypeEnum.allowableValues(),
                BaseBusinessErrorCodeEnum.ENUM_PARAM_MUST_BE_IN_ALLOWABLE_VALUE,
                "orderTypes",
                OrderTypeEnum.allowableValues());

        // 校验 售后状态 传值是否正确
        ParamCheckUtil.checkIntSetAllowableValues(
                param.getOrderTypes(),
                AfterSaleStatusEnum.allowableValues(),
                BaseBusinessErrorCodeEnum.ENUM_PARAM_MUST_BE_IN_ALLOWABLE_VALUE,
                "afterSaleStatus",
                AfterSaleStatusEnum.allowableValues());

        // 校验 售后申请来源 传值是否正确
        ParamCheckUtil.checkIntSetAllowableValues(
                param.getOrderTypes(),
                AfterSaleApplySourceEnum.allowableValues(),
                BaseBusinessErrorCodeEnum.ENUM_PARAM_MUST_BE_IN_ALLOWABLE_VALUE,
                "applySources",
                AfterSaleApplySourceEnum.allowableValues());

        // 校验 售后类型 传值是否正确
        ParamCheckUtil.checkIntSetAllowableValues(
                param.getOrderTypes(),
                AfterSaleStatusEnum.allowableValues(),
                BaseBusinessErrorCodeEnum.ENUM_PARAM_MUST_BE_IN_ALLOWABLE_VALUE,
                "afterSaleTypes",
                AfterSaleStatusEnum.allowableValues());


        Integer maxSize = param.MAX_PAGE_SIZE;
        checkSetMaxSize(param.getAfterSaleIds(),maxSize,"afterSaleIds");
        checkSetMaxSize(param.getOrderIds(),maxSize,"orderIds");
        checkSetMaxSize(param.getUserIds(),maxSize,"userIds");
        checkSetMaxSize(param.getSkuCodes(),maxSize,"skuCodes");
    }


    /**
     * 校验参数size是否超过最大值限制
     * @author xuyou
     * @date: 2022/6/24 14:10
     */
    private void checkSetMaxSize(Set setParam, Integer maxSize, String paramName) {
        BaseBusinessErrorCodeEnum baseBusinessErrorCodeEnum = BaseBusinessErrorCodeEnum.COLLECTION_PARAM_CANNOT_BEYOND_MAX_SIZE;
        ParamCheckUtil.checkSetMaxSize(setParam, maxSize,
                baseBusinessErrorCodeEnum,paramName
                ,maxSize);
    }
}
